import { defineConfig } from "vite";
import type { ResolvedConfig } from "vite";
import path from "path";
import fs from "fs";

// https://vitejs.dev/config/
export default defineConfig({
  server: {
    hmr: {
      protocol: "ws",
      host: "localhost",
    },
  },
  build: {
    lib: {
      entry: path.resolve(__dirname, "src/main.ts"),
      name: "userscript",
      formats: ["iife"], // 自运行打包格式，与默认模版一致
      fileName: (format) => `yourscript.${format}.user.js`, // 非函数的常量会自动添加后缀
    },
    rollupOptions: {
      external: ["vue"], // 分离库以降低最终代码体积
      output: {
        globals: {
          vue: "Vue",
          GM_addStyle: "GM_addStyle", // 油猴脚本API，用于添加样式到页面
        },
        inlineDynamicImports: true, // 库构建模式下不能进行代码分割，开启此功能可将本应分割的代码整合在一起避免报错（代码分割可能由其他插件引起）
      },
    },
    minify: "terser",
    terserOptions: {
      mangle: false, // 关闭名称混淆，遵守Greasefork规则
      format: {
        beautify: true, // 美化代码开启缩进，遵守Greasefork规则
      },
    },
  },

  plugins: [
    // custom plugin
    (() => {
      /**
       * 如果用到了额外的 GM_functions，需要添加对应 @grant
       * 虽然可以全部不添加，但只有TamperMonkey会自动推断，其他扩展不一定
       * 在上面 extenral 声明的库，此处需要添加对应的 @require 要注意全局变量名称
       */
      const headers = `\
 // ==UserScript==
 // @name         Your Script (prod mode)
 // @namespace    https://your.site/
 // @version      0.1.0
 // @description  What does your script do
 // @author       You
 // @include      /https://match\.site/
 // @grant        GM_addStyle
 // @noframes
 // @require      https://cdn.jsdelivr.net/npm/vue@3.2.6/dist/vue.global.min.js
 // ==/UserScript==
 `;
      // 来自vite.config.ts的配置继承
      let viteConfig: ResolvedConfig;

      return {
        name: "my-plugin",
        apply: "build", // 仅在构建模式下启用
        enforce: "post", // 在最后处理
        configResolved (resolvedConfig: ResolvedConfig) {
          viteConfig = resolvedConfig;
        },
        async writeBundle(options: any, bundle: any) {
          for (const file of Object.entries(bundle)) {
            // 获取文件路径
            const root: string = viteConfig.root;
            const outDir: string = viteConfig.build.outDir || "dist";
            const fileName: string = file[0];
            const filePath: string = path.resolve(root, outDir, fileName);
            // 读取文件内容
            let data: string = fs.readFileSync(filePath, {
              encoding: "utf8",
            });

            data = `${headers}\n\n${data}`;

            fs.writeFileSync(filePath, data);
          }
        },
      };
    })(),
  ],
});
